// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_MODEL__
#define __H_MK_MODEL__

#include "mk_mesh.h"
#include "mk_texture_mapping.h"
#include "mk_skeleton.h"

namespace MK3DE
{
	class MK3DE_API CModel
	{
	public:
		static const DWORD VB_DIRTY_NONE = 0;
		static const DWORD VB_DIRTY_FACE_INDEX = 1;
		static const DWORD VB_DIRTY_POS_NORMAL = 1 << 1;
		static const DWORD VB_DIRTY_TEXCOORD = 1 << 2;

	public:
		CModel();
		~CModel();

		BOOL AddSubMesh(const char* fileName, int materialIdx);
		BOOL AddSkeleton(const char* fileName);

		int GetVertexCount();
		int GetFaceCount();

		void SetAnimationInterval(float time);
		void UpdateSkeleton(DWORD dt, BOOL bChanged);
		void PauseAnimation(BOOL bPause) { _bPause = bPause; }

		DWORD GetAnimationCount();
		BOOL UseAnimation(DWORD idx, float time);
		CSkeleton* GetCurrentAnimation() { return _pSkeleton; }
		BOOL GetSkeleton(DWORD idx, /* out */ CSkeleton*& pSkeleton);
		void CalculateSkeletonBaseTranformation();

		int GetSubMeshCount() { return (int)_vecSubMesh.size(); }
		CMesh* GetSubMeshByIdx(int idx);

		int FillVertexBuffer(CMesh::Position* pPosition, CMesh::Normal* pNormal, int vertexNum);
		int FillUVBuffer(CMesh::TextureCoord* puv, int vertexNum);
		int FillSkinBuffer(D3DXVECTOR4* pIndex, D3DXVECTOR4* pWeight, int vertexNum);
		int FillFaceBuffer(CMesh::Face* pFace, int faceNum);

		DWORD PrepareUpdateVertexData();

		std::string GetShaderFile() { return _shaderFile; }

		BOOL CollideWithRay(D3DXMATRIX& mat, D3DXVECTOR3& pos, float x, float y, float z, D3DXVECTOR3& dir);

	public:
		/** internal method */
		void SortSubMeshByMaterialIdx(int materialCount, std::vector<int>& groupSubMeshCount);

	private:
		std::string _shaderFile;

		//! sub mesh list
		std::vector<CMesh*> _vecSubMesh;

		std::vector<CSkeleton*> _vecSkeleton;

		CSkeleton* _pSkeleton;

		//! Which data in vertex buffer has changed.
		DWORD _vertexBufferState;
		DWORD _lastVertexDataChangedTime;

		BOOL _bPause;
	};
};

#endif // __H_MK_MODEL__